# -*- coding: utf-8 -*-
from werkzeug.urls import url_encode
from werkzeug.exceptions import BadRequest

from odoo import api, http, SUPERUSER_ID, _
from odoo.http import request
from odoo.addons.auth_oauth.controllers.main import OAuthLogin as Home, OAuthController as Controller

import requests


#APPID = 'wx6b238290dfbaab4a'  # 你的微信开放平台APPID
# APPSECRET = 'f96ef5682f6b3ed122081fad457a21d7'  # 你的微信开放平台APPSECRET
# REDIRECT_URI = 'http://www.openerp.site'     # 验证通过后回调的地址，也就是你第三方网站地址


class OAuthLogin(Home):

    # 此方法，登录时，拼接url，在odoo,OAuth 配置好相关的微信回调内容。点击微信登录，则会调用拼接好的url去获取微信授权
    def list_providers(self):
        # 获取所有的OAuth服务商
        providers = super(OAuthLogin, self).list_providers()
        for provider in providers:
            # provider['auth_endpoint']获取的就是身份验证网址
            # 服务商的相关字段信息可以在数据库结构中搜索模型auth就可以找到了
            if provider['wx_is']:
                APPID = provider['wx_appid']
                REDIRECT_URI = provider['wx_redirect_uri']
                SCOPE = provider['wx_scope']
                RESPONSE_TYPE = 'code'
                STATE = str(provider['id'])
                # 构造微信请求参数
                params = dict(
                    appid=APPID,  # 你也可以通过provider['client_id']获得，前提是你在界面配置过
                    redirect_uri=REDIRECT_URI + '/wechat',  # 微信回调处理url，后面的wechat是我自己添加的，可改，但要与下面的路径一致
                    response_type=RESPONSE_TYPE, # https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html 需按照要求填写
                    scope=SCOPE,
                    state=STATE  # 我这里把服务商id放在这个参数中
                )
                # 最终的微信登入请求链接,这里需要注意，需要url_encode一下
                provider['auth_link'] = "{}?{}#wechat_redirect".format(provider['auth_endpoint'], url_encode(params))
        return providers


class OAuthController(Controller):
    # 此处的路径'/wechat'与上面所填的redirect_uri要一致
    @http.route('/wechat', type='http', auth='none')
    def login(self, **kwargs):
        oauth = request.env['auth.oauth.provider'].sudo().search([('id', '=', kwargs.get('state', ''))])
        if oauth:
            # OAuth提供商id
            provider_id = kwargs.get('state', '')
            # 以下微信相关 #
            code = kwargs.get('code', '')
            # code换取token
            token_info = self.get_token(CODE=code, APPID=oauth.wx_appid, APPSECRET=oauth.wx_appsecret)
            openid = token_info['openid']
            # 换取用户信息
            user_info = self.get_userinfo(token_info['access_token'], openid)
            res_user = request.env['res.users'].sudo().search([('wx_unionid', '=', user_info['unionid'])], limit=1)
            # 检查是否关注公众号
            public_is = request.env['wx.user'].sudo().search([('unionid', '=', user_info['unionid'])], limit=1)
            if not public_is:
                return http.local_redirect("/xz_login_qr_code")
            if res_user:
                uid = request.session.authenticate(request.session.db, res_user.login, res_user.login_password)
                if uid:
                    return http.local_redirect("/xz_login_ok_thanks")
            else:
                return request.render("odoo-wechat.wx_bind_customer_user_view", {
                    'unionid': user_info['unionid'],
                    'openid': user_info['openid'],
                    'nickname': user_info['nickname'],
                    'sex': user_info['sex'],
                })
        else:
            return http.local_redirect('/web/login')

    def get_token(self, CODE, APPID, APPSECRET):
        # 这里是第二步，通过code获取access_token
        # 链接的第一行也可以在你配置的界面中获取，我是直接写在这里
        url = "https://api.weixin.qq.com/sns/oauth2/access_token?" \
              "appid={}&secret={}&code={}&grant_type=authorization_code".format(APPID, APPSECRET, CODE)
        return self.get_result(url)

    def get_userinfo(self, token, openid):
        url = "https://api.weixin.qq.com/sns/userinfo?access_token={}&openid={}".format(token, openid)
        return self.get_result(url)

    @staticmethod
    def get_result(url):
        res = requests.get(url)
        res.encoding = res.apparent_encoding
        result = res.json()
        if 'errcode' not in result:
            # 返回字典类型数据
            return result
        else:
            # print("res['errmsg']!!!!!!!!!!!!!!!!!!!!!!!!", res['errmsg'])
            raise BadRequest(res['errmsg'])

    @http.route('/MP_verify_3fVcQZhY9M05YwYw.txt', type='http', auth='none')
    def vx_validation_file(self, **kwargs):
        return '3fVcQZhY9M05YwYw'

    # 如果没有找到相关用户，则需要，单独页面进行用户绑定操作, 用户绑定提交路由。
    @http.route('/wx/bind', type='http', auth='public', website=True, sitemap=False, methods=['POST'])
    def web_auth_wx_bind(self, **kw):
        if kw:
            # 获取绑定页面传到后台的有关微信登录的信息
            password = kw.get('password')
            login = kw.get('email')
            wx_openid = kw.get('openid')
            wx_unionid = kw.get('unionid')
            wx_nickname = kw.get('nickname')
            wx_sex = kw.get('sex')
            # 查找绑定用户的账号，在系统中能否找到
            bind_user = request.env['res.users'].sudo().search([('login', '=', login)], limit=1)
            if bind_user:
                assert password
                # 获取用加密密码，然后查询用户名和密码是否匹配
                request.env.cr.execute(
                    "SELECT COALESCE(password, '') FROM res_users WHERE id=%s",
                    [bind_user.id]
                )
                hashed = request.env.cr.fetchone()
                res_user = request.env['res.users'].sudo().search([('login', '=', kw.get('email')), ('password', '=', hashed)], limit=1)
                if res_user:
                    uid = request.session.authenticate(request.session.db, res_user.login, password)
                    if uid:
                        res_user.update({
                            "wx_openid": wx_openid,
                            "wx_unionid": wx_unionid,
                            "wx_nickname": wx_nickname,
                            "wx_sex": wx_sex,
                            "login_password": password,
                        })
                        return http.local_redirect("/xz_login_ok_thanks")
                else:
                    return http.local_redirect('/web/login')
